home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / v10n22.arc / RECORD1.C < prev    next >
C/C++ Source or Header  |  1991-12-08  |  17KB  |  427 lines

  1. /*---------------------------------------------------------
  2.    RECORD1.C -- Multimedia Windows Waveform Audio Recorder
  3.                 (c) Charles Petzold, 1991
  4.   ---------------------------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include <mmsystem.h>
  8. #include <string.h>
  9. #include "record1.h"
  10.  
  11. #define BUFFER_SIZE 16384     // Must be multiple of 2 for memory copies
  12.  
  13. BOOL FAR PASCAL DlgProc (HWND, WORD, WORD, LONG) ;
  14.  
  15. static char szAppName [] = "Record1" ;
  16.  
  17. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  18.                     LPSTR lpszCmdLine, int nCmdShow)
  19.      {
  20.      FARPROC lpDlgProc ;
  21.  
  22.      lpDlgProc = MakeProcInstance (DlgProc, hInstance) ;
  23.      DialogBox (hInstance, szAppName, NULL, lpDlgProc) ;
  24.      FreeProcInstance (lpDlgProc) ;
  25.  
  26.      return 0 ;
  27.      }
  28.  
  29. void HugeMemRev (unsigned char huge *pBuffer, unsigned long lLength)
  30.      {
  31.      unsigned char c ;
  32.      unsigned long l ;
  33.  
  34.      for (l = 0 ; l < lLength / 2 ; l++)
  35.           {
  36.           c = pBuffer [l] ;
  37.           pBuffer [l] = pBuffer [lLength - l - 1] ;
  38.           pBuffer [lLength - l - 1] = c ;
  39.           }
  40.      }
  41.  
  42. BOOL FAR PASCAL DlgProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  43.      {
  44.      static BOOL          bRecording, bPlaying, bReverse, bPaused,
  45.                           bEnding, bTerminating ;
  46.      static BYTE FAR *    pBuffer ;
  47.      static BYTE huge *   pSaveBuffer ;
  48.      static char          szOpenError[] = { "Error opening waveform audio!" } ;
  49.      static char          szMemError[] = { "Error allocating memory!" } ;
  50.      static DWORD         dwDataLength, dwRepetitions = 1 ;
  51.      static GLOBALHANDLE  hSaveBuffer, hNewBuffer, hBuffer, hWaveHdr ;
  52.      static HWAVEIN       hWaveIn ;
  53.      static HWAVEOUT      hWaveOut ;
  54.      static LPWAVEHDR     pWaveHdr ;
  55.      static PCMWAVEFORMAT pcm ;
  56.  
  57.      switch (message)
  58.           {
  59.           case WM_INITDIALOG:
  60.                                         // Allocate Memory for Wave Header
  61.  
  62.                hWaveHdr = GlobalAlloc (GHND | GMEM_SHARE, sizeof (WAVEHDR)) ;
  63.                pWaveHdr = (LPWAVEHDR) GlobalLock (hWaveHdr) ;
  64.  
  65.                                         // Allocate Memory for Save Buffer
  66.  
  67.                hSaveBuffer = GlobalAlloc (GHND | GMEM_SHARE, 1) ;
  68.                pSaveBuffer = GlobalLock (hSaveBuffer) ;
  69.  
  70.                return TRUE ;
  71.  
  72.           case WM_COMMAND:
  73.                switch (wParam)
  74.                     {
  75.                     case ID_RECORD_BEG:
  76.                                         // Allocate Buffer Memory
  77.  
  78.                          hBuffer = GlobalAlloc (GHND | GMEM_SHARE,
  79.                                                 BUFFER_SIZE) ;
  80.  
  81.                          if (hBuffer == NULL)
  82.                               {
  83.                               MessageBeep (MB_ICONEXCLAMATION) ;
  84.                               MessageBox (hwnd, szMemError, szAppName,
  85.                                           MB_ICONEXCLAMATION | MB_OK) ;
  86.                               return TRUE ;
  87.                               }
  88.  
  89.                          pBuffer = GlobalLock (hBuffer) ;
  90.  
  91.                                         // Open Waveform Audio for Input
  92.  
  93.                          pcm.wf.wFormatTag      = WAVE_FORMAT_PCM ;
  94.                          pcm.wf.nChannels       = 1 ;
  95.                          pcm.wf.nSamplesPerSec  = 11025 ;
  96.                          pcm.wf.nAvgBytesPerSec = 11025 ;
  97.                          pcm.wf.nBlockAlign     = 1 ;
  98.                          pcm.wBitsPerSample     = 8 ;
  99.  
  100.                          if (waveInOpen (&hWaveIn, 0, &pcm.wf, hwnd, 0L,
  101.                                          CALLBACK_WINDOW))
  102.                               {
  103.                               GlobalUnlock (hBuffer) ;
  104.                               GlobalFree (hBuffer) ;
  105.  
  106.                               MessageBeep (MB_ICONEXCLAMATION) ;
  107.                               MessageBox (hwnd, szOpenError, szAppName,
  108.                                           MB_ICONEXCLAMATION | MB_OK) ;
  109.                               }
  110.  
  111.                          return TRUE ;
  112.  
  113.                     case ID_RECORD_END:
  114.                                         // Reset Input to Return Last Buffer
  115.  
  116.                          bEnding = TRUE ;
  117.                          waveInReset (hWaveIn) ;
  118.                          return TRUE ;
  119.  
  120.                     case ID_PLAY_BEG:
  121.                                         // Open Waveform Audio for Output
  122.  
  123.                          pcm.wf.wFormatTag      = WAVE_FORMAT_PCM ;
  124.                          pcm.wf.nChannels       = 1 ;
  125.                          pcm.wf.nSamplesPerSec  = 11025 ;
  126.                          pcm.wf.nAvgBytesPerSec = 11025 ;
  127.                          pcm.wf.nBlockAlign     = 1 ;
  128.                          pcm.wBitsPerSample     = 8 ;
  129.  
  130.                          if (waveOutOpen (&hWaveOut, 0, &pcm.wf, hwnd, 0L,
  131.                                          CALLBACK_WINDOW))
  132.                               {
  133.                               MessageBeep (MB_ICONEXCLAMATION) ;
  134.                               MessageBox (hwnd, szOpenError, szAppName,
  135.                                           MB_ICONEXCLAMATION | MB_OK) ;
  136.                               }
  137.  
  138.                          return TRUE ;
  139.  
  140.                     case ID_PLAY_PAUSE:
  141.                                         // Pause or Restart Output
  142.  
  143.                          if (!bPaused)
  144.                               {
  145.                               waveOutPause (hWaveOut) ;
  146.                               SetDlgItemText (hwnd, ID_PLAY_PAUSE, "Resume") ;
  147.                               bPaused = TRUE ;
  148.                               }
  149.                          else
  150.                               {
  151.                               waveOutRestart (hWaveOut) ;
  152.                               SetDlgItemText (hwnd, ID_PLAY_PAUSE, "Pause") ;
  153.                               bPaused = FALSE ;
  154.                               }
  155.  
  156.                          return TRUE ;
  157.  
  158.                     case ID_PLAY_END:
  159.                                         // Reset Output for Close Preparation
  160.  
  161.                          bEnding = TRUE ;
  162.                          waveOutReset (hWaveOut) ;
  163.                          return TRUE ;
  164.  
  165.                     case ID_PLAY_REV:
  166.                                         // Reverse Save Buffer and Play
  167.  
  168.                          bReverse = TRUE ;
  169.                          HugeMemRev (pSaveBuffer, dwDataLength) ;
  170.  
  171.                          SendMessage (hwnd, WM_COMMAND, ID_PLAY_BEG, 0L) ;
  172.                          return TRUE ;
  173.  
  174.                     case ID_PLAY_REP:
  175.                                         // Set Infinite Repetitions and Play
  176.  
  177.                          dwRepetitions = -1 ;
  178.                          SendMessage (hwnd, WM_COMMAND, ID_PLAY_BEG, 0L) ;
  179.                          return TRUE ;
  180.  
  181.                     case ID_PLAY_SPEED:
  182.                                         // Open Waveform Audio for Fast Output
  183.  
  184.                          pcm.wf.wFormatTag      = WAVE_FORMAT_PCM ;
  185.                          pcm.wf.nChannels       = 1 ;
  186.                          pcm.wf.nSamplesPerSec  = 22050 ;
  187.                          pcm.wf.nAvgBytesPerSec = 22050 ;
  188.                          pcm.wf.nBlockAlign     = 1 ;
  189.                          pcm.wBitsPerSample     = 8 ;
  190.  
  191.                          if (waveOutOpen (&hWaveOut, 0, &pcm.wf, hwnd, 0L,
  192.                                          CALLBACK_WINDOW))
  193.                               {
  194.                               MessageBeep (MB_ICONEXCLAMATION) ;
  195.                               MessageBox (hwnd, szOpenError, szAppName,
  196.                                           MB_ICONEXCLAMATION | MB_OK) ;
  197.                               }
  198.  
  199.                          return TRUE ;
  200.                     }
  201.                break ;
  202.  
  203.           case MM_WIM_OPEN:
  204.                                         // Shrink Down the Save Buffer
  205.  
  206.                GlobalUnlock (hSaveBuffer) ;
  207.                hSaveBuffer = GlobalReAlloc (hSaveBuffer, 1, GHND) ;
  208.                pSaveBuffer = GlobalLock (hSaveBuffer) ;
  209.  
  210.                                         // Enable and Disable Buttons
  211.  
  212.                EnableWindow (GetDlgItem (hwnd, ID_RECORD_BEG), FALSE) ;
  213.                EnableWindow (GetDlgItem (hwnd, ID_RECORD_END), TRUE)  ;
  214.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_BEG),   FALSE) ;
  215.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_PAUSE), FALSE) ;
  216.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_END),   FALSE) ;
  217.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_REV),   FALSE) ;
  218.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_REP),   FALSE) ;
  219.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_SPEED), FALSE) ;
  220.                SetFocus (GetDlgItem (hwnd, ID_RECORD_END)) ;
  221.  
  222.                                         // Set Up Header
  223.  
  224.                pWaveHdr->lpData          = pBuffer ;
  225.                pWaveHdr->dwBufferLength  = BUFFER_SIZE ;
  226.                pWaveHdr->dwBytesRecorded = 0L ;
  227.                pWaveHdr->dwUser          = 0L ;
  228.                pWaveHdr->dwFlags         = 0L ;
  229.                pWaveHdr->dwLoops         = 1L ;
  230.                pWaveHdr->lpNext          = NULL ;
  231.                pWaveHdr->reserved        = 0L ;
  232.  
  233.                                         // Prepare and Add
  234.  
  235.                waveInPrepareHeader (hWaveIn, pWaveHdr, sizeof (WAVEHDR)) ;
  236.                waveInAddBuffer (hWaveIn, pWaveHdr, sizeof (WAVEHDR)) ;
  237.  
  238.                                         // Begin Sampling
  239.  
  240.                bRecording = TRUE ;
  241.                bEnding = FALSE ;
  242.                dwDataLength = 0L ;
  243.                waveInStart (hWaveIn) ;
  244.                return TRUE ;
  245.  
  246.           case MM_WIM_DATA:
  247.                                         // Unprepare Header
  248.  
  249.                waveInUnprepareHeader (hWaveIn, pWaveHdr, sizeof (WAVEHDR)) ;
  250.  
  251.                                         // Reallocate Save Buffer Memory
  252.  
  253.                GlobalUnlock (hSaveBuffer) ;
  254.                hNewBuffer = GlobalReAlloc (hSaveBuffer, dwDataLength +
  255.                                            pWaveHdr->dwBytesRecorded, 0) ;
  256.  
  257.                if (hNewBuffer == NULL)
  258.                     {
  259.                     pSaveBuffer = GlobalLock (hSaveBuffer) ;
  260.  
  261.                     waveInClose (hWaveIn) ;
  262.                     MessageBeep (MB_ICONEXCLAMATION) ;
  263.                     MessageBox (hwnd, szMemError, szAppName,
  264.                                 MB_ICONEXCLAMATION | MB_OK) ;
  265.                     return TRUE ;
  266.                     }
  267.  
  268.                hSaveBuffer = hNewBuffer ;
  269.                pSaveBuffer = GlobalLock (hSaveBuffer) ;
  270.  
  271.                _fmemcpy ((char far *) (pSaveBuffer + dwDataLength), pBuffer,
  272.                          (int) pWaveHdr->dwBytesRecorded) ;
  273.  
  274.                dwDataLength += pWaveHdr->dwBytesRecorded ;
  275.  
  276.                if (bEnding)
  277.                     {
  278.                     waveInClose (hWaveIn) ;
  279.                     return TRUE ;
  280.                     }
  281.  
  282.                                         // Set the Header, Prepare and Add
  283.  
  284.                pWaveHdr->lpData          = pBuffer ;
  285.                pWaveHdr->dwBufferLength  = BUFFER_SIZE ;
  286.                pWaveHdr->dwBytesRecorded = 0L ;
  287.                pWaveHdr->dwUser          = 0L ;
  288.                pWaveHdr->dwFlags         = 0L ;
  289.                pWaveHdr->dwLoops         = 1L ;
  290.                pWaveHdr->lpNext          = NULL ;
  291.                pWaveHdr->reserved        = 0L ;
  292.  
  293.                waveInPrepareHeader (hWaveIn, pWaveHdr, sizeof (WAVEHDR)) ;
  294.                waveInAddBuffer (hWaveIn, pWaveHdr, sizeof (WAVEHDR)) ;
  295.  
  296.                return TRUE ;
  297.  
  298.           case MM_WIM_CLOSE:
  299.                                         // Free the Buffer Memory
  300.                GlobalUnlock (hBuffer) ;
  301.                GlobalFree (hBuffer) ;
  302.  
  303.                                         // Enable and Disable Buttons
  304.  
  305.                EnableWindow (GetDlgItem (hwnd, ID_RECORD_BEG), TRUE) ;
  306.                EnableWindow (GetDlgItem (hwnd, ID_RECORD_END), FALSE) ;
  307.                SetFocus (GetDlgItem (hwnd, ID_RECORD_BEG)) ;
  308.  
  309.                if (dwDataLength > 0)
  310.                     {
  311.                     EnableWindow (GetDlgItem (hwnd, ID_PLAY_BEG),   TRUE)  ;
  312.                     EnableWindow (GetDlgItem (hwnd, ID_PLAY_PAUSE), FALSE) ;
  313.                     EnableWindow (GetDlgItem (hwnd, ID_PLAY_END),   FALSE) ;
  314.                     EnableWindow (GetDlgItem (hwnd, ID_PLAY_REP),   TRUE)  ;
  315.                     EnableWindow (GetDlgItem (hwnd, ID_PLAY_REV),   TRUE)  ;
  316.                     EnableWindow (GetDlgItem (hwnd, ID_PLAY_SPEED), TRUE)  ;
  317.                     SetFocus (GetDlgItem (hwnd, ID_PLAY_BEG)) ;
  318.                     }
  319.  
  320.                bRecording = FALSE ;
  321.  
  322.                if (bTerminating)
  323.                     SendMessage (hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L) ;
  324.  
  325.                return TRUE ;
  326.  
  327.           case MM_WOM_OPEN:
  328.                                         // Enable and Disable Buttons
  329.  
  330.                EnableWindow (GetDlgItem (hwnd, ID_RECORD_BEG), FALSE) ;
  331.                EnableWindow (GetDlgItem (hwnd, ID_RECORD_END), FALSE) ;
  332.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_BEG),   FALSE) ;
  333.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_PAUSE), TRUE)  ;
  334.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_END),   TRUE)  ;
  335.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_REP),   FALSE) ;
  336.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_REV),   FALSE) ;
  337.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_SPEED), FALSE) ;
  338.                SetFocus (GetDlgItem (hwnd, ID_PLAY_END)) ;
  339.  
  340.                                         // Set Up Header
  341.  
  342.                pWaveHdr->lpData          = (char far *) pSaveBuffer ;
  343.                pWaveHdr->dwBufferLength  = dwDataLength ;
  344.                pWaveHdr->dwBytesRecorded = 0L ;
  345.                pWaveHdr->dwUser          = 0L ;
  346.                pWaveHdr->dwFlags         = WHDR_BEGINLOOP | WHDR_ENDLOOP ;
  347.                pWaveHdr->dwLoops         = dwRepetitions ;
  348.                pWaveHdr->lpNext          = NULL ;
  349.                pWaveHdr->reserved        = 0L ;
  350.  
  351.                                         // Prepare and Write
  352.  
  353.                waveOutPrepareHeader (hWaveOut, pWaveHdr, sizeof (WAVEHDR)) ;
  354.                waveOutWrite (hWaveOut, pWaveHdr, sizeof (WAVEHDR)) ;
  355.  
  356.                bEnding = FALSE ;
  357.                bPlaying = TRUE ;
  358.                return TRUE ;
  359.  
  360.           case MM_WOM_DONE:
  361.                waveOutUnprepareHeader (hWaveOut, pWaveHdr, sizeof (WAVEHDR)) ;
  362.                waveOutClose (hWaveOut) ;
  363.                return TRUE ;
  364.  
  365.           case MM_WOM_CLOSE:
  366.                                         // Enable and Disable Buttons
  367.  
  368.                EnableWindow (GetDlgItem (hwnd, ID_RECORD_BEG), TRUE)  ;
  369.                EnableWindow (GetDlgItem (hwnd, ID_RECORD_END), TRUE)  ;
  370.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_BEG),   TRUE)  ;
  371.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_PAUSE), FALSE) ;
  372.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_END),   FALSE) ;
  373.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_REV),   TRUE)  ;
  374.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_REP),   TRUE)  ;
  375.                EnableWindow (GetDlgItem (hwnd, ID_PLAY_SPEED), TRUE)  ;
  376.                SetFocus (GetDlgItem (hwnd, ID_PLAY_BEG)) ;
  377.  
  378.                SetDlgItemText (hwnd, ID_PLAY_PAUSE, "Pause") ;
  379.                bPaused = FALSE ;
  380.                dwRepetitions = 1 ;
  381.                bPlaying = FALSE ;
  382.  
  383.                if (bReverse)
  384.                     {
  385.                     HugeMemRev (pSaveBuffer, dwDataLength) ;
  386.                     bReverse = FALSE ;
  387.                     }
  388.  
  389.                if (bTerminating)
  390.                     SendMessage (hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L) ;
  391.  
  392.                return TRUE ;
  393.  
  394.           case WM_SYSCOMMAND:
  395.                switch (wParam)
  396.                     {
  397.                     case SC_CLOSE:
  398.                          if (bRecording)
  399.                               {
  400.                               bTerminating = TRUE ;
  401.                               bEnding = TRUE ;
  402.                               waveInReset (hWaveIn) ;
  403.                               return TRUE ;
  404.                               }
  405.  
  406.                          if (bPlaying)
  407.                               {
  408.                               bTerminating = TRUE ;
  409.                               bEnding = TRUE ;
  410.                               waveOutReset (hWaveOut) ;
  411.                               return TRUE ;
  412.                               }
  413.  
  414.                          GlobalUnlock (hWaveHdr) ;
  415.                          GlobalFree (hWaveHdr) ;
  416.  
  417.                          GlobalUnlock (hSaveBuffer) ;
  418.                          GlobalFree (hSaveBuffer) ;
  419.  
  420.                          EndDialog (hwnd, 0) ;
  421.                          return TRUE ;
  422.                     }
  423.                break ;
  424.           }
  425.      return FALSE ;
  426.      }
  427.